<template>
	<div>jstest</div>
</template>

<script>
	import {
		ref,
		reactive
	} from 'vue'
	export default {
		data() {
			return {}
		},
		mounted() {
			this.birthDay();
			this.birthDay('1~8'); //1~8天过生日
			this.filterEmpty();
			this.objectTest();
			this.testPromiseAll();
			this.pAllTest();
			this.stringTest();
			this.onceTest();
			this.userAgentTest();
			this.testSet();
			this.testMap();
			var dateTime = this.formatTime1();
			console.log('dateTime', dateTime)
			this.matrix()
			this.reduceTest()
			this.sortTest()
			this.filterFalse()
			this.filterSample()
			this.stringCount()
			this.arraySort()
			this.isPalindrome()
		},
		methods: {
			//默认16~31天过生日
			birthDay(query = '16~31') {
				var [startDay, endDay] = query.split('~').map(it => it)
				console.log(startDay, endDay)

			},

			//去除对象中的 value 为 null，''，undefined 的 key 
			filterEmpty() {
				console.log('=============filterEmpty')

				function isEmpty(input) {
					return ['', undefined, null].includes(input)
				}

				function isObject(input) {
					return input !== null && (!Array.isArray(input)) && typeof input === 'object'
				}

				function filterParams(obj) {
					const keys = Object.keys(obj)
					keys.forEach(key => {
						const value = obj[key]
						if (isObject(value)) filterParams(value)
						if (isEmpty(value)) delete obj[key]
					})
					return obj
				}
				var obj = {
					a: 1,
					b: null,
					c: '',
					d: undefined,
					e: {
						e1: 1
					},
				}
				obj = filterParams(obj)
				console.log('obj', obj)
			},

			//对象上的函数
			objectTest() {
				console.log('=============objectTest')

				//熟悉Object.defineProperty或者说熟悉对象API的人，一般是如下代码写的，则不会出现被修改的问题
				function Vue() {
					console.log('test vue');
				};

				function http() {
					console.log('我是调用接口的http');
				};
				// Vue.prototype.$router=http
				// var vm =new Vue;
				// vm.$route()
				// vm.$route=1 // 一旦被修改，虽然一般正常情况下不会被修改
				// vm.$route // 再次调用报错

				Object.defineProperty(Vue.prototype, '$http', {
					get() {
						return http;
					}
				})
				var vm = new Vue();
				vm.$http()
				// vm.$http = 1; // 这里无法修改。修改会报错
				// vm.$http() 	

				//对于数组，Object.assign()把数组视为属性名为 0、1、2 的对象。
				console.log('相当于数组对象，索引角标就是对应的key，如arr1[0],key=0')
				var arr1 = [1, 2, 3]
				var arr2 = [4, 5]
				Object.assign(arr1, arr2); // [4,5,3]
				console.log('arr1', arr1)

				//Object.fromEntries() 是 Object.entries()的逆操作
				var arr = [
					['a', 1],
					['b', 2],
					['c', 3]
				];
				var obj = Object.fromEntries(arr); // {a: 1, b: 2, c: 3}
				console.log('obj', obj)
			},

			async testPromiseAll() {
				var result = await Promise.all([1, Promise.resolve(2)])
				console.log('=============testPromiseAll')
				console.log('result', result) //result  [1, 2]
				try {
					var result = await Promise.all([1, Promise.reject(2)])
						.catch(e => console.log(e, '<- Error')) // 2 "<- Error"
				} catch (e) {
					//TODO handle the exception
				}

				var result = await Promise.all([1, Promise.resolve(2), 3])
				console.log('result', result) //result  [1, 2 ,3]
			},
			//手写一个 Promise.all,大概就是维护一个promise数组，把所有promise都执行，当返回结果的长度=数组的长度，说明所有promise执行完毕，resovle返回结果
			pAll(_promises) {
				return new Promise((resolve, reject) => {
					// Iterable => Array
					const promises = Array.from(_promises)
					// 结果用一个数组维护
					const r = []
					const len = promises.length
					let count = 0
					for (let i = 0; i < len; i++) {
						// Promise.resolve 确保把所有数据都转化为 Promise
						Promise.resolve(promises[i]).then(o => {
							// 因为 promise 是异步的，保持数组一一对应
							r[i] = o;

							// 如果数组中所有 promise 都完成，则返回结果数组
							if (++count == len) {
								resolve(r)
							}
							// 当发生异常时，直接 reject
						}).catch(e => reject(e))
					}
				})
			},
			// 为了测试，实现一个 sleep 函数
			sleep(seconds) {
				return new Promise(resolve => setTimeout(() => resolve(seconds), seconds))
			},
			//以下示例进行测试，没有问题
			pAllTest() {
				console.log('=============pAllTest')
				console.log('=============手写一个 Promise.all')
				this.pAll([1, 2, 3]).then(o => console.log('pAllTest=', o)) //[1, 2, 3]
				this.pAll([this.sleep(3000), this.sleep(2000), this.sleep(1000)])
					.then(o => console.log('pAllTest=', o)) //[3000, 2000, 1000]
				this.pAll([this.sleep(3000), this.sleep(2000), this.sleep(1000), Promise.reject(4000)])
					.then(o => console.log('pAllTest=', o))
					.catch(e => console.log('pAllTest=', e, '<- Error')) //4000 "<- Error"
			},

			//stringTest
			stringTest() {
				console.log('=============stringTest')
				console.log('String(arr[])等价于arr[].toString()')
				console.log(String([1, 2, 3])) // 1,2,3
				console.log(JSON.stringify([1, 2, 3])) // [1,2,3]
				const obj = {
					title: 'devpoint',
					//toString方法被重写
					toString() {
						return "obj";
					},
				};
				console.log(String(obj)) // obj
				console.log(JSON.stringify(obj)) // {"title":"devpoint"}

				const runToString = (obj) => Object.prototype.toString.call(obj);
				console.log(runToString({})) // [object Object]
			},

			//一个函数只执行一次
			onceTest() {
				console.log('=============onceTest')

				function once(fn) {
					let called = false;
					console.log('called', called)
					return function() {
						if (!called) {
							called = true;
							fn.apply(this, arguments)
						}
					}
				}

				function launchRocket() {
					console.log("我已经执行了");
				}
				const launchRocketOnce = once(launchRocket);
				launchRocketOnce();
				launchRocketOnce();
				launchRocketOnce();
			},

			//浏览器嗅探
			userAgentTest() {
				console.log('=============userAgentTest')
				const isBrowser = typeof window !== "undefined"; //浏览器环境window
				const UA = isBrowser && window.navigator.userAgent.toLowerCase(); //获取浏览器的userAgent
				//检查userAgent来确定当前的浏览器供应商和操作系统
				const isIE = UA && /msie|trident/.test(UA);
				const isIE9 = UA && UA.indexOf("msie 9.0") > 0;
				const isEdge = UA && UA.indexOf("edge/") > 0;
				const weexPlatform = window.navigator.platform
				const isAndroid = (UA && UA.indexOf("android" > 0)) || weexPlatform === "android";
				const isIOS = (UA && /iphone|ipad|ipod|ios/.test(UA)) || weexPlatform === "ios";
				const isChrome = (UA && /chrome\/\d+/.test(UA)) && !isEdge; //Edge和Chrome均基于Chromium
				console.log('isAndroid=', isAndroid, 'isIOS=', isIOS, )
			},

			testSet() {
				console.log('=============testSet')
				var arr = [1, 1, 2, 3]
				var unique = [...new Set(arr)]
				console.log('unique', unique)

				let a = new Set([1, 2, 3]);
				let b = new Set([4, 3, 2]);
				// 并集
				let union = [...new Set([...a, ...b])];
				// 交集
				let intersect = [...new Set([...a].filter(x => b.has(x)))]
				console.log('intersect', intersect)
				// 差集
				let difference = Array.from(new Set([...a].filter(x => !b.has(x))))
				console.log('difference', difference)
			},
			testMap() {
				console.log('=============testMap')
				//Map 转换 Array
				var map = new Map([
					[1, 1],
					[2, 2],
					[3, 3]
				])
				console.log([...map]) //[[1, 1],[2, 2],[3, 3]]
				console.log(Array.from(map)) //[[1, 1],[2, 2],[3, 3]]

				// 非字符串键名会被转换为字符串
				function mapToObj(map) {
					let obj = Object.create(null)
					for (let [key, value] of map) {
						obj[key] = value
					}
					return obj
				}
				var map = new Map().set('name', 'vue3js.cn').set('age', '18')
				var mapObj = mapToObj(map)
				console.log('mapObj', mapObj)
			},

			//转换时间格式 2021/06/23 16:05:20
			formatTime1(date = new Date()) {
				console.log('=============formatTime')
				const year = date.getFullYear()
				const month = date.getMonth() + 1
				const day = date.getDate()
				const hour = date.getHours()
				const minute = date.getMinutes()
				const second = date.getSeconds()
				const formatNumber = n => {
					n = n.toString()
					return n[1] ? n : '0' + n
				}
				return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber)
					.join(':')
			},

			//初始化二维数组/矩阵
			matrix() {
				var array = Array(5).fill('');
				var matrix = Array(5).fill(0).map(() => Array(5).fill(0))
				console.log('matrix', matrix) // [Array(5), Array(5), Array(5), Array(5), Array(5)]
			},

			//找出总和、最小值和最大值
			reduceTest() {
				console.log('=============reduceTest')
				var array = [5, 4, 7, 8, 9, 2]
				var sum = array.reduce((a, b) => a + b)
				var max = array.reduce((a, b) => a > b ? a : b)
				var min = array.reduce((a, b) => a < b ? a : b)
				console.log('sum', sum, 'max', max, 'min', min)
			},

			//对字符串、数字或对象数组进行排序
			sortTest() {
				console.log('=============sortTest')
				var array = ["Joe", "Kapil", "Steve", "Musk"]
				array.sort()
				console.log('array', array) //["Joe", "Kapil", "Musk", "Steve"]
				var array = [40, 100, 1, 5, 25, 10]
				array.sort((a, b) => a - b) //第一次：100-40>0,顺序不变
				console.log('array', array) //[1, 5, 10, 25, 40, 100]
			},

			//从数组中过滤出虚假值，Boolean用来移除所有的 ” falsey“ 类型元素（false, null, 0, "", undefined, NaN）
			filterFalse() {
				console.log('=============filterFalse')
				var array = [3, 0, 6, 7, '', false];
				var array2 = array.filter(Boolean);
				console.log('array2', array2)
				//Boolean等价于item=>Boolean(item)
				var array3 = array.filter(item => Boolean(item));
				console.log('array3', array3)//array3 [3, 6, 7]
			},

			//删除重复值
			filterSample() {
				console.log('=============filterSample')
				var array = [5, 4, 7, 8, 9, 2, 7, 5]
				//通过对比索引实现去重，过滤得到第一次出现当前元素的索引
				var array2 = array.filter((item, index, arr) => arr.indexOf(item) == index)
				console.log('array2', array2)
				//set去重
				var array3 = [...new Set(array)]
				console.log('array3', array3)
			},

			//创建计数器对象或映射
			stringCount() {
				console.log('=============stringCount')
				var string = 'kapilalipak'
				var table = {}
				for (let char of string) {
					table[char] = table[char] + 1 || 1 //巧用加法判断是否有值
				}
				console.log('table', table) //{k: 2, a: 3, p: 2, i: 2, l: 2}
				//map
				var countMap = new Map()
				for (let i = 0; i < string.length; i++) {
					var key = string[i]
					if (countMap.has(key)) {
						countMap.set(key, countMap.get(key) + 1)
					} else {
						countMap.set(key, 1)
					}
				}
				console.log('countMap', countMap) //{"k" => 2, "a" => 3, "p" => 2, "i" => 2, "l" => 2}
			},

			//打乱数组
			arraySort() {
				console.log('=============arraySort')
				var array = [1, 2, 3, 4, 5, 6, 7, 8, 9]
				//利用生成的随机数-0.5得到正数或者负数，从而随机的实现倒序和正序
				var array2 = array.sort(() => {
					return Math.random() - 0.5;
				})
				console.log('array2', array2)
				var array3 = array.sort(() => {
					return Math.random() - 0.5;
				})
				console.log('array3', array3)
			},

			//回文检查
			isPalindrome() {
				console.log('=============isPalindrome')

				function checkPalindrome(str) {
					return str == str.toString().split('').reverse().join('');
				}
				console.log('123', checkPalindrome(123))
				console.log('121', checkPalindrome('121'))
			},

		},
	}
</script>

<style>
</style>
